Skip to content

Babel preset: Add Hermes V1 native runtime workarounds for hermes#1761#56816

Closed
ramonclaudio wants to merge 1 commit into
react:mainfrom
ramonclaudio:fix/hermes-v1-bug-workarounds
Closed

Babel preset: Add Hermes V1 native runtime workarounds for hermes#1761#56816
ramonclaudio wants to merge 1 commit into
react:mainfrom
ramonclaudio:fix/hermes-v1-bug-workarounds

Conversation

@ramonclaudio

@ramonclaudio ramonclaudio commented May 13, 2026

Copy link
Copy Markdown

Summary:

Three Babel plugins for @react-native/babel-preset that work around live codegen bugs in the bundled Hermes V1 (250829098.0.13). They rewrite the offending source patterns at compile time so Hermes never sees them. Port of @kitten's plugins in babel-preset-expo (expo/expo#45601, MIT).

The three fixes exist on Hermes static_h but were never grafted onto the shipped 250829098.0.0-stable branch (absent through the .0.15 tip; the only in-flight graft, facebook/hermes#2030, is still open), so the bugs are live on the compiler RN ships. The super-in-object-accessor bug SIGSEGVs hermesc at compile time.

Changelog:

[GENERAL] [FIXED] - Work around three Hermes V1 source-level codegen bugs in @react-native/babel-preset (async-arrow non-simple params, class-in-finally, super-in-object-accessor)

Test Plan:

Test repro at ramonclaudio/hermes-1761-repro. 55/55 PASS on iPhone 17 Pro / iOS 26.5 in both Debug and Release; 4 added edge-case tests (numeric-key accessor, class-name preservation) are verified at the compiler level below.

Locally on packages/react-native-babel-preset:

  • 21 inline-snapshot unit tests cover the transformed output and the skip-when-irrelevant path.
  • yarn jest packages/react-native-babel-preset clean (76 tests, 27 snapshots).
  • Full repo yarn test clean (278 suites, 5692 tests, 1857 snapshots).
  • yarn lint, yarn format-check, yarn flow-check, yarn test-typescript, yarn featureflags --verify-unchanged, yarn build-types --validate all clean.
  • Existing transform-snapshot-test is unchanged: the kitchen-sink fixture has none of the bug patterns so the new plugins don't alter its output.
  • Compiled the bug patterns through the bundled compiler (hermes-compiler@250829098.0.14): get x() { return super.x } and get 0() { return super.x } both SIGSEGV hermesc, while the transformed computed-key output compiles clean. A full Metro bundle of the repro (--minify false, the flags RN's Hermes build uses) compiles clean on hermesc for iOS and Android.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label May 13, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label May 13, 2026
@ramonclaudio ramonclaudio force-pushed the fix/hermes-v1-bug-workarounds branch 2 times, most recently from a5fff17 to b2e38cc Compare May 14, 2026 20:18
@meta-codesync

meta-codesync Bot commented May 18, 2026

Copy link
Copy Markdown

@CalixTang has imported this pull request. If you are a Meta employee, you can view this in D105609206.

@ramonclaudio

Copy link
Copy Markdown
Author

Anything I can do to help push this forward @CalixTang?

@ramonclaudio ramonclaudio force-pushed the fix/hermes-v1-bug-workarounds branch from b2e38cc to 0b32635 Compare June 2, 2026 20:18
@CalixTang

Copy link
Copy Markdown
Contributor

sorry for late response - I don't recall exactly what happened/changed with this PR. Linking another team member onto this.

@ramonclaudio ramonclaudio force-pushed the fix/hermes-v1-bug-workarounds branch from 0b32635 to 8c26985 Compare June 3, 2026 18:54
## Summary:

Three Babel plugins added to `@react-native/babel-preset` that work
around runtime codegen bugs in the bundled Hermes V1 (250829098.0.13,
branch cut 2025-08-29) by rewriting source patterns before they reach
the engine. Each plugin papers over a different bug that is fixed on
Hermes `static_h` but has not been backported to the V1 stable branch
(verified absent through the .0.15 stable tip; the only in-flight graft,
facebook/hermes#2030, is still open).

- `fix-hermes-v1-async-arrow-non-simple-params`:
  facebook/hermes#1761 (fixed in static_h by 68bfb3a48b31, 2025-09-11).
  Async arrow functions with destructured, defaulted, or rest parameters
  silently resolve `await` with `undefined` while the function body
  continues executing in the background. The plugin rewrites the params
  to a simple identifier with inline destructuring so Hermes never sees
  the buggy shape. Gated on `isHermesProfile && preserveAsync` since
  `plugin-transform-async-to-generator` rewrites the pattern away when
  `preserveAsync` is false.

- `fix-hermes-v1-class-in-finally`:
  Fixed in static_h by 1e94fbe0ebb4 (2026-02-12). Class declarations
  inside a `finally` block trip Hermes V1's variable caching path. The
  plugin wraps them in an IIFE so the class lives in its own scope, and
  preserves the inferred name of a class expression bound to a plain
  identifier.

- `fix-hermes-v1-super-in-object-accessor`:
  Fixed in static_h by 18a963465944 (2025-11-04). Object-literal getters
  and setters using `super.x` trip the `genFunctionExpression` home
  object path, which segfaults hermesc at compile time. The plugin marks
  the accessor as computed with a string key, covering identifier,
  string, and numeric keys.

All three gate on `isHermesProfile` and bail out fast on the common
case. The plugins are a direct port of work by @kitten (Phil Pluckthun,
Expo team) in `babel-preset-expo` (expo/expo#45601, MIT licensed). All
plugin design and implementation credit belongs to him. This PR carries
his work over to `@react-native/babel-preset` so bare React Native
consumers benefit from the same fix.

## Changelog:

[GENERAL] [FIXED] - Work around three Hermes V1 source-level codegen bugs in `@react-native/babel-preset` (async-arrow non-simple params, class-in-finally, super-in-object-accessor)

## Test Plan:

- 21 inline-snapshot test cases across three new test files verify the transformed output, the fast-bail behavior on irrelevant patterns, and the numeric-key and class-name edge cases.
- `yarn jest packages/react-native-babel-preset` clean (76 tests, 27 snapshots).
- Full repo `yarn test` clean (278 suites, 5692 tests passed, 1857 snapshots).
- `yarn lint`, `yarn format-check`, `yarn flow-check`, `yarn test-typescript`, `yarn featureflags --verify-unchanged`, `yarn build-types --validate` all clean.
- Existing `transform-snapshot-test` passes byte-identical: the kitchen-sink fixture has none of the buggy patterns so the new plugins do not change its output for any profile.
- Compiled the bug patterns through the bundled compiler (hermes-compiler 250829098.0.14): `get x() { return super.x }` and `get 0() { return super.x }` both segfault hermesc, while the transformed computed-key output compiles clean.
- Device repro at ramonclaudio/hermes-1761-repro: 55/55 PASS on iPhone 17 Pro / iOS 26.5 in Debug and Release.

## Caveats:

`fix-hermes-v1-class-in-finally` rewrites block-scoped `class`
declarations inside `finally` blocks to function-scoped `var`
initializers, matching the babel-preset-expo source. Observable only
when code in the same `finally` references the class before its
declaration or relies on its block scoping (rare). The same plugin shape
has shipped in `babel-preset-expo` and Expo SDK 56 without reported
regressions, but flagging in case Meta's internal test fleet surfaces an
edge case the OSS suite does not catch.

## References:

- facebook/hermes#1761 (root-cause issue, fixed in static_h)
- facebook/hermes#2030 (in-flight graft of the async-arrow fix onto the V1 stable branch, still open)
- expo/expo#45601 (source of the ported plugins, by @kitten)
- expo/expo#45592 (user-facing bug report on SDK 56 preview)

Co-authored-by: Phil Pluckthun <phil@kitten.sh>
@ramonclaudio ramonclaudio force-pushed the fix/hermes-v1-bug-workarounds branch from 8c26985 to 6377bb8 Compare June 3, 2026 19:23
@ramonclaudio

Copy link
Copy Markdown
Author

sorry for late response - I don't recall exactly what happened/changed with this PR. Linking another team member onto this.

No worries. Thank you! @CalixTang

@cortinico

Copy link
Copy Markdown
Contributor

The three fixes exist on Hermes static_h but were never grafted onto the shipped 250829098.0.0-stable branch (absent through the .0.15 tip; the only in-flight graft, facebook/hermes#2030, is still open), so the bugs are live on the compiler RN ships. The super-in-object-accessor bug SIGSEGVs hermesc at compile time.

Why can't we cherry pick those 3 fixes in the 250829098.0.0-stable branch of Hermes instead?

@robhogan

robhogan commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

The three fixes exist on Hermes static_h but were never grafted onto the shipped 250829098.0.0-stable branch (absent through the .0.15 tip; the only in-flight graft, facebook/hermes#2030, is still open), so the bugs are live on the compiler RN ships. The super-in-object-accessor bug SIGSEGVs hermesc at compile time.

Why can't we cherry pick those 3 fixes in the 250829098.0.0-stable branch of Hermes instead?

Yeah this seems strongly preferable to me - @tmikov might have context on whether they're pick-friendly.

These are the ones, IIUC (as listed in expo/expo#45601):

@ramonclaudio

ramonclaudio commented Jun 4, 2026

Copy link
Copy Markdown
Author

Yeah this seems strongly preferable to me - @tmikov might have context on whether they're pick-friendly.

@robhogan I agree. All three pick cleanly onto 250829098.0.0-stable.

I opened #2045 and #2046 to go with the existing #2030 fix upstream.

@cortinico

Copy link
Copy Markdown
Contributor

Closing this + abandoning D105609206

@cortinico cortinico closed this Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants